package com.ruiysoft.util;


import org.apache.commons.lang3.StringUtils;

import java.math.BigDecimal;
import java.math.RoundingMode;
import java.text.DecimalFormat;
import java.util.HashMap;
import java.util.Map;
import java.util.regex.Pattern;

/**
 * description
 *
 * @usage
 */
public class NumberUtils {
    private static final BigDecimal BIG_DEC_ZERO = new BigDecimal(0);

    private static final BigDecimal BIG_DEC_HUNDRED = new BigDecimal(100);
    
    private final static int [] sizeTable = { 9, 99, 999, 9999, 99999, 999999, 9999999,
            99999999, 999999999, Integer.MAX_VALUE };
    

    /**
     * 将BigDecimal型的金额转换成金额显示形式(小数点后两位,多余位忽略)
     *
     * @param desAmount
     * @return 金额(不为空)
     */
    public static String toStringAmount(BigDecimal desAmount) {
        if (desAmount == null) {
            return "";
        }

        return desAmount.setScale(2, BigDecimal.ROUND_DOWN).toString();
    }

    

    /**
     * 验证指定字符串是否为指定长度的数字字符串
     *
     * @param numStr
     * @param length
     * @return
     */
    public static boolean isNumberForLength(String numStr, int length) {
        String regex = "[0-9]{" + length + "}";
        return numStr != null && Pattern.matches(regex, numStr);
    }

    /**
     * 验证指定字符串是否为指定长度的数字字符串
     *
     * @param numStr
     * @return
     */
    public static boolean isNumberForLength(String numStr) {
        if (numStr == null) {
            return false;
        }

        return isNumberForLength(numStr, numStr.length());
    }

    /**
     * 是数字
     *
     * @param str
     * @return
     */
    public static boolean isDouble(String str) {
        try {
            Double.valueOf(str);
            return true;
        } catch (Throwable e) {
            return false;
        }
    }

    /**
     * 是整数
     *
     * @param str
     * @return
     */
    public static boolean isLong(String str) {
        try {
            Long.valueOf(str);
            return true;
        } catch (Throwable e) {
            return false;
        }
    }

    /**
     * 是整数
     *
     * @param str
     * @return
     */
    public static boolean isInteger(String str) {
        //如果字符串根本不是数字,则直接返回false;
        if (!isNumber(str)) {
            return false;
        }

        //不过数字不包含小数点,则直接视为整数
        int dotIndex = str.indexOf('.');
        if (dotIndex == -1) {
            return true;
        }

        //对于存在小数点的,将其放大一万倍,看齐是否大于1来判断是否为整数
        String substring = "0" + str.substring(dotIndex);
        double valueOf = Double.valueOf(substring).doubleValue();
        return valueOf * 100000000 < 1;
    }

    private static boolean isNumber(String str) {
        try {
            Double.parseDouble(str);
            return true;
        } catch (Throwable t) {
            return false;
        }
    }

    /**
     * 是金钱
     *
     * @param money
     * @return
     */
    public static boolean isMoney(String money) {
        if (!isNumber(money)) {
            return false;
        }
        if (money.equals("0")) {
            return false;
        }
        for (int i = 0; i < money.length(); i++) {
            char ch = money.charAt(i);
            if (i == 0) {
                if (ch == '.') {
                    return false;
                }
                if (ch == '0') {
                    char ch1 = money.charAt(i + 1);
                    if (ch1 != '.') {
                        return false;
                    }
                }
            }
            if (!isDigital(ch)) {
                return false;
            }
        }
        try {
            double d = Double.parseDouble(money);

            if (d < 0.01) {

                return false;
            }
        } catch (Exception e) {
            return false;
        }
        if (money.contains(".")) {
            int start = money.indexOf(".") + 1;
            String suffix = money.substring(start, money.length());
            if (suffix.length() > 2) {
                return false;
            }
        }
        return true;
    }

    public static boolean isDigital(char c) {
        if (c == '1' || c == '2' || c == '3' || c == '4' || c == '5' || c == '6' || c == '7' || c == '8' || c == '9' || c == '0' || c == '.') {
            return true;
        }
        return false;
    }
    
    

	// Requires positive x
	public static int stringSize(int x) {
		for (int i=0; ; i++)
		if (x <= sizeTable[i])
		return i+1;
	}

    /**
     * 校验身份证的校验码
     */
    @SuppressWarnings("unchecked")
    public static boolean verifyCid(String idcard) {
        Map month = new HashMap();
        month.put("01", "01");
        month.put("03", "03");
        month.put("05", "05");
        month.put("07", "07");
        month.put("08", "08");
        month.put("10", "10");
        month.put("12", "12");

        if (!isNumber(idcard)) {
            return false;
        }
        if (idcard.length() == 15) {
            idcard = uptoeighteen(idcard);
        }
        if (idcard.length() != 18) {
            return false;
        }
        if (month.containsKey(idcard.substring(10, 12))) {
            if (Integer.valueOf(idcard.substring(12, 14)) > 31) {
                return false;
            }
        } else if (idcard.substring(10, 12).equals("02")) {
            if (Integer.valueOf(idcard.substring(12, 14)) > 29) {
                return false;
            }
        } else {
            if (Integer.valueOf(idcard.substring(12, 14)) > 30) {
                return false;
            }
        }
        String verify = idcard.substring(17, 18);
        if (verify.equals(getVerify(idcard))) {
            return true;
        }
        return false;
    }

    // 15位转18位
    public static String uptoeighteen(String fifteen) {
        String eightcardid = fifteen.substring(0, 6);
        eightcardid = eightcardid + "19";
        eightcardid = eightcardid + fifteen.substring(6, 15);
        eightcardid = eightcardid + getVerify(eightcardid);
        return eightcardid;
    }

    // 计算最后一位校验值
    public static String getVerify(String eighteen) {
        // wi =2(n-1)(mod 11);加权因子
        int[] wi = {7, 9, 10, 5, 8, 4, 2, 1, 6, 3, 7, 9, 10, 5, 8, 4, 2, 1};
        // 校验码
        int[] vi = {1, 0, 'X', 9, 8, 7, 6, 5, 4, 3, 2};
        int[] ai = new int[18];

        int remain = 0;
        if (eighteen.length() == 18) {
            eighteen = eighteen.substring(0, 17);
        }
        if (eighteen.length() == 17) {
            int sum = 0;
            for (int i = 0; i < 17; i++) {
                String k = eighteen.substring(i, i + 1);
                ai[i] = Integer.valueOf(k);
            }
            for (int i = 0; i < 17; i++) {
                sum += wi[i] * ai[i];
            }
            remain = sum % 11;
        }
        return remain == 2 ? "X" : String.valueOf(vi[remain]);
    }

    /**
     * 转换数字为大写金额的字符(注:小数点后最多支持两位[角分])
     *
     * @param value
     * @return
     */
    public static String numberToBig(double value) {
        char[] hunit = {'拾', '佰', '仟'}; //段内位置表示
        char[] vunit = {'万', '亿'}; //段名表示
        char[] digit = {'零', '壹', '贰', '叁', '肆', '伍', '陆', '柒', '捌', '玖'};//数字表示
        long midVal = (long) (value * 100); //转化成整形
        String valStr = String.valueOf(midVal); //转化成字符串
        String head = "";
        String rail = "";
        if (valStr.equals("0")) {
            return "零元";
        } else if (valStr.length() < 2) {
            head = "0";
            rail = "0" + valStr; //取小数部分
        } else {
            head = valStr.substring(0, valStr.length() - 2); //取整数部分
            rail = valStr.substring(valStr.length() - 2); //取小数部分
        }
        String prefix = ""; //整数部分转化的结果
        String suffix = ""; //小数部分转化的结果
        //处理小数点后面的数
        if (rail.equals("00"))//如果小数部分为0
        {
            suffix = "整";
        } else {
            suffix = digit[rail.charAt(0) - '0'] + "角" + digit[rail.charAt(1) - '0'] + "分";
        }
        //处理小数点前面的数
        char[] chDig = head.toCharArray(); //把整数部分转化成字符数组
        char zero = '0'; //标志'0'表示出现过0
        byte zeroSerNum = 0; //连续出现0的次数
        for (int i = 0; i < chDig.length; i++) { //循环处理每个数字
            int idx = (chDig.length - i - 1) % 4; //取段内位置
            int vidx = (chDig.length - i - 1) / 4; //取段位置
            if (chDig[i] == '0') { //如果当前字符是0
                zeroSerNum++; //连续0次数递增
                if (zero == '0') { //标志
                    zero = digit[0];
                } else if (idx == 0 && vidx > 0 && zeroSerNum < 4) {
                    prefix += vunit[vidx - 1];
                    zero = '0';
                }
                continue;
            }
            zeroSerNum = 0; //连续0次数清零
            if (zero != '0') { //如果标志不为0,则加上,例如万,亿什么的
                prefix += zero;
                zero = '0';
            }
            prefix += digit[chDig[i] - '0']; //转化该数字表示
            if (idx > 0)
                prefix += hunit[idx - 1];
            if (idx == 0 && vidx > 0) {
                prefix += vunit[vidx - 1];
            }//段结束位置应该加上段名如万,亿
        }

        if (prefix.length() > 0)
            prefix += '元'; //如果整数部分存在,则有圆的字样
        String result = prefix + suffix; //返回正确表示
        if (result.startsWith("零角")) {
            return result.substring(2);
        }

        return result;
    }


    /**
     * 取得指定范围的随机数 注:取得的值不包含最大值(例如:max=3时值为0,1,2)
     *
     * @param maxValue
     * @return
     */
    public static int getRandomIntInMax(int maxValue) {
        return (int) (Math.random() * maxValue % maxValue);
    }

    /**
     * 对资金进行格式化
     *
     * @param amount
     * @return
     */
    public static String formatAmount(BigDecimal amount) {
        if (amount == null) {
            return null;
        }

        return amount.setScale(2, BigDecimal.ROUND_DOWN).toString();
    }


    /**
     * 小数点右移
     *
     * @param number
     * @param n      右移的位数
     * @return 移位后的数字字符串
     */
    public static String rightMove(String number, int n) {
        BigDecimal decimal = new BigDecimal(number);
        return decimal.movePointRight(n).toString();
    }

    /**
     * 小数点左移，
     *
     * @param number
     * @param n      移位后的字符串
     * @return
     */
    public static String leftMove(String number, int n) {
        BigDecimal bd = new BigDecimal(number);
        return bd.movePointLeft(n).toString();

    }

    /**
     * 相加
     *
     * @param number1
     * @param number2
     * @return
     */
    public static String add(String number1, String number2) {
        BigDecimal bd = new BigDecimal(number1);
        return bd.add(new BigDecimal(number2)).toString();
    }

    /**
     * 相乘
     *
     * @return
     */
    public static String multiplyHundred(String number1, String number2) {
        return new BigDecimal(number1).multiply(new BigDecimal(number2)).toString();
    }

    /**
     * 乘以100
     *
     * @param num
     * @return
     */
    public static BigDecimal multiplyHundred(BigDecimal num) {
        if (num == null) {
            return null;
        }
        return num.multiply(BIG_DEC_HUNDRED);
    }

    /**
     * 除以100
     *
     * @param num
     * @return
     */
    public static BigDecimal divideHundred(BigDecimal num) {
        if (num == null) {
            return null;
        }
        return num.divide(BIG_DEC_HUNDRED);
    }

    /**
     * 金额为分的格式
     */
    public static final String CURRENCY_FEN_REGEX = "\\-?[0-9]+";


    /**
     * 标题:    changeF2Y
     * 描述:    将分为单位的转换为元 （除100） 保留2位小数
     * 参数:    @param amount 以分为单位的金额
     * 返回类型: String<br/> 以元单位的金额
     * 异常:    金额格式不对
     * 创建者:  xu_qing
     * 日期    : 2014年9月4日 上午9:39:53
     * 修改者:
     * 修改日期    :
     * 修改备注    :
     */
    public static String changeF2Y(String amount) throws Exception {
        if (StringUtils.isBlank(amount)) {
            return "0";
        }
        if (!amount.matches(CURRENCY_FEN_REGEX)) {
            throw new Exception("金额格式有误("+ amount+")");
        }
        DecimalFormat df = new DecimalFormat("#0.00");
        return df.format(divideHundred(new BigDecimal(amount)));
    }


    /**
     * 标题:    changeF2Y
     * 描述:    将分为单位的转换为元 （除100） 保留2位小数，四舍五入
     * 参数:    @param amount 以分为单位的金额
     * 返回类型: String<br/> 以元单位的金额
     * 异常:    金额格式不对
     * 创建者:  xu_qing
     * 日期    : 2014年9月4日 上午9:39:53
     * 修改者:
     * 修改日期    :
     * 修改备注    :
     */
    public static String changeF2Y2(String amount){
        if (StringUtils.isBlank(amount)) {
            return "0";
        }
        return divideHundred(new BigDecimal(amount)).setScale(2, RoundingMode.HALF_UP).toString();
    }

    /**
     * 标题:    changeY2F
     * 描述:    将元为单位的转换为分 （乘100）
     * 参数:    @param amount 以元为单位的金额
     * 返回类型: String<br/>  以分为单位的金额
     * 创建者: xu_qing
     * 日期    : 2014年9月4日 上午9:41:33
     * 修改者:
     * 修改日期    :
     * 修改备注    :
     */
    public static String changeY2F(String amount) throws RuntimeException {
        if (StringUtils.isBlank(amount)) {
            return amount;
        }
//        if(!amount.matches(CURRENCY_FEN_REGEX)) {
//            throw new Exception("金额格式有误");
//        }
//        DecimalFormat df =new DecimalFormat("#0.00");
//        return df.format(multiplyHundred(new BigDecimal(amount)));
        return String.valueOf(multiplyHundred(new BigDecimal(amount)).longValue());
    }
    //利润率
    public static BigDecimal getPercentInstance(long a,long b) throws Exception {
    	
  	  return getPercentInstance(new BigDecimal(a),new BigDecimal(b));
    }
    //利润率
    public static BigDecimal getPercentInstance(BigDecimal a,BigDecimal b) throws Exception {
    	BigDecimal percentI = a.divide(b,4,BigDecimal.ROUND_DOWN).multiply(new BigDecimal(100));
    	return percentI;
    }
    
    public static boolean compareSize(String a, String b, String c) throws Exception {
        if (StringUtils.isBlank(a) || StringUtils.isBlank(b) || StringUtils.isBlank(c)) {
            return false;
        }
        if (Double.parseDouble(c) >= Double.parseDouble(a) && Double.parseDouble(c) < Double.parseDouble(b)) {
            return true;
        }
        return false;
    }

    public static String afterNum(String input,int num){
        return input.substring(input.length()-num);
    }

}
